import {
  useDebounceFn,
  useGetState,
  useMemoizedFn,
  useMount,
  useSafeState,
  useUnmount,
} from "ahooks";
import { getValueOrDie, sleep } from "@common/utils";
import { useContext } from "react";
import { GlobalModel } from "@/ui/context";
import { BrowserSession } from "@common/models";
import * as xhsRPC from "@/ui/utils/rpc/xhs";
import { retry } from "@common/utils/misc";
import { v4 as uuid } from "uuid";
import { omit } from "lodash-es";
import { Props } from "./meta";

export function useViewModel(props: Props) {
  const { commentReplyTo, onReplyToClick } = props;
  const [loadBtnId] = useSafeState<string>(
    () => "b" + uuid().replace(/-/g, ""),
  );
  const [loading, setLoading, getLoading] = useGetState(true);
  const globalModels = getValueOrDie(useContext(GlobalModel));
  const discussion = getValueOrDie(globalModels.discussion);
  const [loadBtnObserver, setLoadBtnObserver] =
    useSafeState<IntersectionObserver>();

  const isInited = useMemoizedFn(
    () => !(discussion.comments.hasMore && !discussion.comments.records.length),
  );

  const sessionOfOwner = useMemoizedFn(() => {
    return globalModels.sessions.find(
      (s) => s.apps.xhs.user?.user_id === discussion.ownerId,
    );
  });

  // 滚动talk list 到底部
  // const scrollToBottom = useMemoizedFn((wait = 500) => {
  //   const listTag = document.querySelector(
  //     "#app > div > div.area-c > div > div.talk-list",
  //   );
  //   setTimeout(() => {
  //     listTag?.scrollTo({
  //       top: listTag.scrollHeight - listTag.clientHeight,
  //       behavior: "smooth",
  //     });
  //   }, wait);
  // });

  // 滚动talk list 到底部
  // const scrollToTop = useMemoizedFn((wait = 500) => {
  //   const listTag = document.querySelector(
  //     "#app > div > div.area-c > div > div.talk-list",
  //   );
  //   setTimeout(() => {
  //     listTag?.scrollTo({
  //       top: 0,
  //       behavior: "smooth",
  //     });
  //   }, wait);
  // });

  const loadComments = useDebounceFn(
    async () => {
      const isPageInited = isInited();
      console.log("加载评论", isPageInited);
      if (!globalModels.sessions.length) {
        alert("至少需要登录一个账号");
      } else {
        const session = sessionOfOwner();
        if (!session) {
          alert(`被提及的账号【ownerId:${discussion.ownerId}】当前未登录`);
          return;
        }
        setLoading(true);
        const result = await xhsRPC.loadCommentsInNote({
          isPageInited,
          noteId: discussion.note.noteId,
          xsecToken: discussion.note.xsecToken,
          targetId: session.apps.xhs.targetId,
        });
        if (!isPageInited) {
          discussion.comments = result;
        } else {
          discussion.comments.hasMore = result.hasMore;
          discussion.comments.records = discussion.comments.records.concat(
            result.records,
          );
        }

        setLoading(false);
      }
    },
    { wait: 500, leading: true, trailing: false },
  );
  const loadSubComments = (commentId: string) => async () => {
    const session = sessionOfOwner();
    if (!session) {
      alert(`会话所属账号【ownerId: ${discussion.ownerId}】已退出，请重新登录`);
      return;
    }
    const result = await xhsRPC.loadMoreSubCommentsInNote({
      noteId: discussion.note.noteId,
      xsecToken: discussion.note.xsecToken,
      targetId: session.apps.xhs.targetId,
      rootCommentId: commentId,
    });
    const rootComment = getValueOrDie(
      discussion.comments.records.find((r) => r.id === commentId),
    );
    rootComment.sub_comment_has_more = result.hasMore;
    rootComment.sub_comments = rootComment.sub_comments?.concat(result.records);
  };

  const init = useDebounceFn(
    async () => {
      setLoading(true);
      await loadComments.flush();
      setLoading(false);

      setTimeout(async () => {
        const observer = new IntersectionObserver(
          (entries) => {
            if (entries[0].intersectionRatio <= 0) return;

            if (!getLoading() && discussion.comments.hasMore) {
              loadComments.run();
            }
          },
          {
            root: document.querySelector(".talk-list"),
            threshold: 0.2,
          },
        );
        observer.observe(
          await retry(async (failTimes) => {
            if (failTimes) {
              await sleep(1000);
            }
            return getValueOrDie(document.querySelector(`.load-more-button`));
          }),
        );

        setLoadBtnObserver(observer);
      }, 500);
    },
    { wait: 500, leading: true, trailing: false },
  );

  const post = useMemoizedFn(
    async (content: string, sendAsSession: BrowserSession) => {
      const sendTaskId = uuid();
      discussion.sendQueue.push(sendTaskId);
      const newComment = await xhsRPC.replyToCommentInNote({
        targetId: sendAsSession.apps.xhs.targetId,
        noteId: discussion.note.noteId,
        xsecToken: discussion.note.xsecToken,
        comment: commentReplyTo
          ? omit(
              commentReplyTo,
              "pictures",
              "sub_comment_count",
              "sub_comment_cursor",
              "content",
              "sub_comment_has_more",
              "sub_comments",
              "target_comment",
            )
          : undefined,
        sessionId: sendAsSession.id,
        content,
      });

      // 插入到预期位置
      if (commentReplyTo) {
        (() => {
          for (let i = 0; i < discussion.comments.records.length - 1; ++i) {
            const topComment = getValueOrDie(discussion.comments.records[i]);
            if (topComment.id === newComment.target_comment?.id) {
              if (!topComment.sub_comments) {
                topComment.sub_comments = [];
              }
              topComment.sub_comments.unshift(newComment);
              return;
            }
            if (topComment.sub_comments) {
              for (let j = 0; j < topComment.sub_comments?.length; ++j) {
                const c = getValueOrDie(topComment.sub_comments[j]);
                if (c.id === newComment.target_comment?.id) {
                  topComment.sub_comments.splice(j + 1, 0, newComment);
                  topComment.sub_comments = [...topComment.sub_comments];
                  return;
                }
              }
            }
          }
        })();
      } else {
        discussion.comments.records = [
          newComment,
          ...discussion.comments.records,
        ];
      }
      discussion.sendQueue = discussion.sendQueue.filter(
        (r) => r !== sendTaskId,
      );

      if (onReplyToClick) {
        onReplyToClick(undefined);
      }
    },
  );

  useMount(init.run);
  useUnmount(() => {
    loadBtnObserver?.disconnect();
  });

  return {
    loading,
    globalModels,
    commentToReply: props.commentReplyTo,
    loadBtnId,
    post,
    realSender: props.realSender,
    records: discussion.comments.records ?? [],
    hasMore: discussion.comments.hasMore,

    loadComments,
    loadSubComments,
    setReplyTo: onReplyToClick,
  };
}
